<?php
/**
 * Created by PhpStorm.
 * User: figo-009
 * Date: 2017/5/25
 * Time: 10:40:41
 */
namespace ApigilityGroup\Service;

use ApigilityOrder\DoctrineEntity\Order;
use Zend\ServiceManager\ServiceManager;
use Zend\Hydrator\ClassMethods as ClassMethodsHydrator;
use Doctrine\ORM\QueryBuilder;
use Doctrine\ORM\Tools\Pagination\Paginator as DoctrineToolPaginator;
use DoctrineORMModule\Paginator\Adapter\DoctrinePaginator as DoctrinePaginatorAdapter;
use ApigilityGroup\DoctrineEntity;
use ApigilityUser\DoctrineEntity\User;
use ApigilityGroup\DoctrineEntity\ParticipationDetail;
use ApigilityAddress\DoctrineEntity\Region;

class ParticipationDetailService
{
    const SEX_MALE = 1;
    const SEX_FEMALE = 2;

    const TYPE_CREATOR = 1;
    const TYPE_PARTICIPANT = 2;

    protected $classMethodsHydrator;

    /**
     * @var \Doctrine\ORM\EntityManager
     */
    protected $em;

    /**
     * @var \ApigilityGroup\Service\GroupService
     */
    protected $groupService;

    /**
     * @var GroupSettingService
     */
    protected $groupsettingService;

    /**
     * @var \ApigilityVIP\Service\ContractService
     */
    protected $contract;

    /**
     * @var orderService
     */
    protected $orderService;

    protected $serviceManager;

    protected $userService;

    /**
     * @var \ApigilitySocial\Service\PersonService
     */
    protected $personService;

    public function __construct(ServiceManager $services)
    {
        $this->classMethodsHydrator = new ClassMethodsHydrator();
        $this->em = $services->get('Doctrine\ORM\EntityManager');
        $this->groupService = $services->get('ApigilityGroup\Service\GroupService');
        $this->groupsettingService = $services->get('ApigilityGroup\Service\SettingService');
        $this->contract = $services->get('ApigilityVIP\Service\ContractService');
        $this->serviceManager = $services;
        $this->userService = $services->get('ApigilityUser\Service\UserService');
        $this->orderService = $services->get('ApigilityOrder\Service\OrderService');
        $this->personService = $services->get('ApigilitySocial\Service\PersonService');
    }

    /**
     * 创建一个团购活动
     *
     * @param $data
     * @return DoctrineEntity\ParticipationDetail
     */
    public function createParticipationDetail($data, $user = '', $contract_id = '', $creator = false)
    {
        $participation = new DoctrineEntity\ParticipationDetail();

        $participation_details = $this->getParticipationDetailsByUser($user);

        if(count($participation_details) >= 1) {
            if($participation_details[0]->getStatus()==0){
                $group = $this->groupService->getGroupByBuyNumber($data->buy_number);
                $group_setting = $group->getGroupSetting();
                if($group->getMaleParticipationNums() + $group->getFemaleParticipationNums() >= $group_setting->getBeingGroupNums()) {
                    throw new \Exception('该团人数已满', 404);
                }

                if($participation_details[0]->getGroup()->getId() == $group->getId()){
                    return $participation_details[0];
                }else if($participation_details[0]->getUser()->getId()!=$participation_details[0]->getGroup()->getUser()->getId()){
                    $this->deleteParticipationDetail($participation_details[0]->getId());
                    $this->contract->deleteContract($participation_details[0]->getContract()->getId());
                }
            }else{
                throw new \Exception('一个用户不能参与多次拼团活动', 404);
            }
        }

        $census_register_address = $user->getCensusRegisterAddress();
        if(empty($census_register_address)) {
            throw new \Exception('请先填写户籍地址', 404);
        }

        $group = $this->groupService->getGroupByBuyNumber($data->buy_number);
        $group_setting = $group->getGroupSetting();
        $participation->setUser($user);
        $participation->setGroup($group);
        $participation->setStatus(0);

        if($group->getMaleParticipationNums() + $group->getFemaleParticipationNums() >= $group_setting->getBeingGroupNums()) {
            throw new \Exception('该团人数已满', 404);
        }

        $sex = $user->getSex();
        $has_free = false;
        $is_free_area = false;
        if ($census_register_address->getProvince() == $group_setting->getProvince() &&
            $census_register_address->getCity() == $group_setting->getCity() &&
            $census_register_address->getDistrict() == $group_setting->getDistrict()
        ) {
            $is_free_area = true;
        }

        // 当有人参团时，根据不同的参团方式修改参团人数
        $price = $group_setting->getPrice();
        $census_group_setting = $this->groupsettingService->getGroupSettingByAddress($census_register_address->getProvince(), $census_register_address->getCity(), $census_register_address->getDistrict());

        if($sex == $this::SEX_MALE){
            if($census_group_setting[0]->getMaleFreeLeftNums()) {
                $group->setMaleFreeParticipationNums($group->getMaleFreeParticipationNums() + 1);
                $census_group_setting[0]->setMaleFreeLeftNums($census_group_setting[0]->getMaleFreeLeftNums() - 1);
                $group->setMaleParticipationNums($group->getMaleParticipationNums() + 1);
                $price = 0;
                $has_free = true;
            }

        } else {
            if($census_group_setting[0]->getFemaleFreeLeftNums()) {
                $group->setFemaleFreeParticipationNums($group->getFemaleFreeParticipationNums() + 1);
                $census_group_setting[0]->setFemaleFreeLeftNums($census_group_setting[0]->getFemaleFreeLeftNums() - 1);
                $group->setFemaleParticipationNums($group->getFemaleParticipationNums() + 1);
                $price = 0;
                $has_free = true;
            }
        }

        $participation->setType($creator ? $this::TYPE_CREATOR : $this::TYPE_PARTICIPANT);
        $participation->setPrice($price);
        $participation->setParticipationTime(new \DateTime());

        // 参团者(非创建拼团者)，需要调用合约服务生成合约
        $contract_data = new \stdClass();
        $contract_data->user_id = $user->getId();
        $contract_data->service_id = $group->getServices()[0]->getId();
        $contract_data->price = $price;
        $contract = $this->serviceManager->get('ApigilityVIP\Service\ContractService')->createContract($contract_data, $user);

        //$contract = $this->contract->getContract($contract_id ? $contract_id : $contract->getId());
        $contracts = $this->contract->getContractsByUser($user); // 获取某个用户已有的合约列表
        $participation->setExpires(
            count($contracts) ?
                (new \DateTime())->setTimestamp($contracts[0]->getExpireTime()->getTimestamp() + $group->getServices()[0]->getExpire()) :
                (new \DateTime())->setTimestamp((new \DateTime())->getTimestamp() + $group->getServices()[0]->getExpire())
        );
        $contract->setEffectiveTime(count($contracts) ? $contracts[0]->getExpireTime() : $contract->getEffectiveTime());
        $contract->setExpireTime($participation->getExpires()); // 把参团时间更新到合约过期时间

        $participation->setContract($contract);
        $participation->setOrder($contract->getOrder());
        if($has_free){
            $participation->setStatus(1);
        }else{
            $participation->setStatus(0);
        }

        $this->em->persist($participation);
        $this->em->flush();
        if($has_free && $price==0){
            $participation_details = $this->getParticipationDetailsByGroupId($group->getId());
            if (count($participation_details) >= $group_setting->getBeingGroupNums()) {
                foreach ($participation_details as $participation_detail) {
                    $u = $this->userService->getUser($participation_detail->getUser()->getId());
                    $contract = $this->contract->getContractByOrderId($participation_detail->getOrder()->getId());
                    $contracts = $this->contract->getContractsByUser($u); // 获取某个用户已有的合约列表
                    $expire_time = count($contracts) ? (new \DateTime())->setTimestamp($contracts[0]->getExpireTime()->getTimestamp() + $contract->getService()->getExpire()) :
                        (new \DateTime())->setTimestamp((new \DateTime())->getTimestamp() + $contract->getService()->getExpire());
                    $participation_detail->setExpires($expire_time);
                    $contract->setEffectiveTime(count($contracts) ? $contracts[0]->getExpireTime() : $contract->getEffectiveTime());
                    $contract->setExpireTime($expire_time);
                    $person = $this->personService->getPersonByUserId($participation_detail->getUser()->getId());
                    $person->setVipStatus($participation_detail->getContract()->getService()->getStatus());
                    $person->setVipExpireTime($participation_detail->getExpires());
                    $this->contract->getContract($participation_detail->getContract()->getId())->getOrder()->setStatus(3);
                    $participation_detail->setStatus(1);
                    $this->em->flush();

                    /*if($person->getVipExpireTime() < $expire_time && count($contracts)>0){
                        $contract->setEffectiveTime(count($contracts) ? $contracts[0]->getExpireTime() : $contract->getEffectiveTime());
                        $contract->setExpireTime($expire_time);
                        $this->em->flush();
                    }*/
                }
            }
        }
        /*$participation_details = $this->getParticipationDetailsByGroupId($group->getId());
        if (count($participation_details) >= $group_setting->getBeingGroupNums()) {
            foreach ($participation_details as $participation_detail) {
                $person = $this->serviceManager->get('ApigilitySocial\Service\PersonService')->getPersonByUserId($participation_detail->getUser()->getId());
                $person->setVipStatus($participation_detail->getContract()->getService()->getStatus());
                $person->setVipExpireTime($participation_detail->getExpires());
                $this->contract->getContract($participation_detail->getContract()->getId())->getOrder()->setStatus(3);
                $this->em->flush();
            }
        }*/

        return $participation;
    }

    /**
     * 获取一个拼团活动
     *
     * @param $group_setting_id
     * @return DoctrineEntity\Setting
     * @throws \Exception
     */
    public function getParticipationDetail($Participation_etail_id)
    {
        $participation = $this->em->find('ApigilityGroup\DoctrineEntity\ParticipationDetail', $Participation_etail_id);

        if (empty($participation)) {
            throw new \Exception(' 参团详情不存在', 404);
        } else {
            return $participation;
        }
    }

    /**
     * 获取一个拼团活动
     *
     * @param $group_setting_id
     * @return DoctrineEntity\Setting
     * @throws \Exception
     */
    public function getGroupSettingByAddress($province, $city, $district)
    {
        $groups = $this->em->getRepository('ApigilityGroup\DoctrineEntity\Setting')
            ->findBy([
            'province' => $province,
            'city' => $city,
            'district' => $district,
        ]);

        if (count($groups)) {
            return $groups;
        } else {
            throw new \Exception('拼团活动不存在', 404);
        }
    }

    /**
     * 获取拼团活动列表
     *
     * @param $params
     * @return DoctrinePaginatorAdapter
     */
    public function getParticipationDetails($params, $status=1)
    {
        $qb = new QueryBuilder($this->em);
        $qb->select('p')->from('ApigilityGroup\DoctrineEntity\ParticipationDetail', 'p');

        $where = '';

        if($status == 1){
            $where = 'p.status=1';
        }

        if (isset($params->group_id)) {
            $qb->innerJoin('p.group', 'pg');
            if (!empty($where)) $where .= ' AND ';
            $where .= 'pg.id = :group_id';
        }

        if (isset($params->user_id)) {
            $qb->innerJoin('p.user', 'pu');
            if (!empty($where)) $where .= ' AND ';
            $where .= 'pu.id = :user_id';
        }

        if (!empty($where)) {
            $qb->where($where);
            if (isset($params->group_id)) $qb->setParameter('group_id', $params->group_id);
            if (isset($params->user_id)) $qb->setParameter('user_id', $params->user_id);
        }

        $qb->orderBy('p.id', 'desc');

        $doctrine_paginator = new DoctrineToolPaginator($qb->getQuery());
        return new DoctrinePaginatorAdapter($doctrine_paginator);
    }

    /**
     * 获取一个拼团，根据用户获取
     *
     * @param $user
     * @return DoctrineEntity\Group
     * @throws \Exception
     */
    public function getParticipationDetailsByUser(User $user, $status=null)
    {
        $params = array('user'=>$user->getId());
        if($status){
            $params['status'] = $status;
        }
        $group = $this->em->getRepository('ApigilityGroup\DoctrineEntity\ParticipationDetail')->findBy($params);

        return $group;
    }

    /**
     * 获取拼团详情,根据拼团id获取
     *
     * @param $group_id
     * @return DoctrineEntity\
     * @throws \Exception
     */
    public function getParticipationDetailsByGroupId($group_id,$status = 1)
    {
        $param = array('group'=>$group_id);
        if($status){
            $param['status'] = 1;
        }
        $participations = $this->em->getRepository('ApigilityGroup\DoctrineEntity\ParticipationDetail')->findBy($param);

        return $participations;
    }

    /**
     * 获取一个拼团,很具拼团id获取
     *
     * @param $group_id
     * @return DoctrineEntity\Group
     * @throws \Exception
     */
    public function getPayNumsByGroupId($group_id, $sex = null)
    {
        $qb = new QueryBuilder($this->em);
        $qb->select('count(p.id) as total')->from('ApigilityGroup\DoctrineEntity\ParticipationDetail', 'p');

        $where = 'p.price != 0';
        if (isset($group_id)) {
            $qb->innerJoin('p.group', 'pg');
            if (!empty($where)) $where .= ' AND ';
            $where .= 'pg.id = :group_id';
        }

        $qb->innerJoin('p.order', 'po');
        if (!empty($where)) $where .= ' AND ';
        $where .= 'po.id = p.order AND po.status = 3';
        
        if(!empty($sex)) {
            $qb->innerJoin('p.user', 'pu');
            if (!empty($where)) $where .= ' AND ';
            $where .= 'pu.id = p.user AND pu.sex = :sex';
        }

        if (!empty($where)) {
            $qb->where($where);
            if (isset($group_id)) $qb->setParameter('group_id', $group_id);
            if (isset($sex)) $qb->setParameter('sex', ($sex == $this::SEX_MALE ? $this::SEX_MALE : $this::SEX_FEMALE));
        }

        $res = $qb->getQuery()->getResult();
        if(count($res)) {
            return $res[0]['total'];
        } else {
            return 0;
        }
    }

    /**
     * 获取一个拼团，根据用户获取
     *
     * @param $user
     * @return DoctrineEntity\Group
     * @throws \Exception
     */
    public function getParticipationDetailsByOrder(Order $order)
    {
        $group = $this->em->getRepository('ApigilityGroup\DoctrineEntity\ParticipationDetail')->findBy([
            'order' => $order->getId(),
        ]);

        return $group;
    }

    /**
     * 删除一个拼团
     *
     * @param $group_setting_id
     * @return bool
     * @throws \Exception
     */
    public function deleteParticipationDetail($participation_detail_id)
    {
        $participation = $this->getParticipationDetail($participation_detail_id);

        $this->em->remove($participation);
        $this->em->flush();

        return true;
    }
}